package com.hnyfkj.jyindustry.common.config;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.hnyfkj.jyindustry.common.oauth2.OAuth2Filter;
import com.hnyfkj.jyindustry.common.oauth2.OAuth2Realm;
import com.hnyfkj.jyindustry.common.shiroredis.RedisCacheManager;
import com.hnyfkj.jyindustry.common.shiroredis.RedisSessionDAO;

/**
 * @program: jyindustry
 * @description:shiro配置类
 * @author: zl
 * @create: 2020-07-09 18:05
 **/
@Configuration
public class ShiroConfig {

	@Value("${excludes}")
	private String excludes;
	@Value("${effectTime}")
	private String effectTime;

	@Bean
	public RedisSessionDAO sessionDAO() {
		return new RedisSessionDAO();
	}

	@Bean("sessionManager")
	public SessionManager sessionManager() {
		final DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
		sessionManager.setSessionValidationSchedulerEnabled(true);
		sessionManager.setSessionIdUrlRewritingEnabled(false);
		// sessionManager.setSessionIdCookieEnabled(false);
		sessionManager.setSessionDAO(sessionDAO());
		sessionManager.setGlobalSessionTimeout(1800000);
		sessionManager.setCacheManager(redisCacheManager());
		return sessionManager;
	}

	@Bean("securityManager")
	public SecurityManager securityManager(final SessionManager sessionManager) {
		final DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(oAuth2Realm());
		securityManager.setSessionManager(sessionManager);
		// 权限缓存有问题，不使用默认方法，自己写缓存方法
		// securityManager.setCacheManager(redisCacheManager());
		return securityManager;
	}

	@Bean("shiroFilter")
	public ShiroFilterFactoryBean shirFilter(final SecurityManager securityManager) {
		final ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
		shiroFilter.setSecurityManager(securityManager);

		// oauth过滤
		final Map<String, Filter> filters = new HashMap<>();
		filters.put("oauth2", new OAuth2Filter());
		shiroFilter.setFilters(filters);

		final Map<String, String> filterMap = new LinkedHashMap<>();
		filterMap.put("/webjars/**", "anon");
		filterMap.put("/druid/**", "anon");
		filterMap.put("/api/**", "anon");
		filterMap.put("/images/**", "anon");
		filterMap.put("/lib/**", "anon");
		filterMap.put("/js/**", "anon");
		filterMap.put("/page/**", "anon");

		// swagger配置
		filterMap.put("/swagger**", "anon");
		filterMap.put("/v2/api-docs", "anon");
		filterMap.put("/swagger-resources/configuration/ui", "anon");

		filterMap.put("/**/*.css", "anon");
		filterMap.put("/**/*.js", "anon");
		filterMap.put("/**/*.html", "anon");
		filterMap.put("/fonts/**", "anon");
		filterMap.put("/plugins/**", "anon");
		filterMap.put("/favicon.ico", "anon");
		filterMap.put("/captcha", "anon");
		filterMap.put("/barbar/**", "anon");
		// filterMap.put("/sys/login", "anon");
		final String[] anonArray = excludes.split(",");
		for (final String newAnon : anonArray) {
			filterMap.put(newAnon, "anon");
		}
		filterMap.put("/**", "oauth2");

		shiroFilter.setFilterChainDefinitionMap(filterMap);

		return shiroFilter;
	}

	@Bean("lifecycleBeanPostProcessor")
	public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
		return new LifecycleBeanPostProcessor();
	}

	@Bean
	public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		final DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
		proxyCreator.setProxyTargetClass(true);
		return proxyCreator;
	}

	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
			final SecurityManager securityManager) {
		final AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
		advisor.setSecurityManager(securityManager);
		return advisor;
	}

	@Bean
	public RedisCacheManager redisCacheManager() {
		return new RedisCacheManager();
	}

	/**
	 * 告诉加密算法
	 * 
	 * @return
	 */
	@Bean("hashedCredentialsMatcher")
	public HashedCredentialsMatcher hashedCredentialsMatcher() {
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		hashedCredentialsMatcher.setHashAlgorithmName("MD5");// 采用MD5 进行加密
		hashedCredentialsMatcher.setHashIterations(Integer.valueOf(effectTime));// 加密次数
		return hashedCredentialsMatcher;
	}

	/**
	 * 配置realm，用于认证和授权
	 * 
	 * @param hashedCredentialsMatcher
	 * @return
	 */
	@Bean
	public OAuth2Realm oAuth2Realm() {
		OAuth2Realm oAuth2Realm = new OAuth2Realm();
		// 校验密码用到的算法
		oAuth2Realm.setCredentialsMatcher(hashedCredentialsMatcher());
		return oAuth2Realm;
	}
}
